package com.smartplatform.websocket;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.HashMultimap;
import com.smartplatform.event.DevicePowerCommandEvent;
import com.smartplatform.event.SysHumitureCheckEvent;
import com.smartplatform.pojo.SysHumiture;
import com.smartplatform.service.SysHumitureService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Author 咕唧
 * @Date 2022/6/10 15:10
 * @Version 1.0
 */
@Component
@EnableAsync(proxyTargetClass = true)
public class MyDHT11Handler extends MyBaseWebSocketHandler {
    //创建一个map,泛型其实是一个集合
    HashMultimap<String, SysHumiture> humitureHashMultimap = HashMultimap.create();

    private static Map<String, Long> heartbeatTime = new ConcurrentHashMap<>();

    private static Map<String, WebSocketSession> allClient = new ConcurrentHashMap<>();

    private ObjectMapper objectMapper;

    private SysHumitureService sysHumitureService;

    @Autowired
    public void setSysHumitureService(SysHumitureService sysHumitureService) {
        this.sysHumitureService = sysHumitureService;
    }

    @Autowired
    public void setObjectMapper(ObjectMapper objectMapper) {
        this.objectMapper = objectMapper;
    }

    /**
     * 收到消息后执行
     *
     * @param session
     * @param message
     * @throws Exception
     */
    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        super.handleTextMessage(session, message);
        System.out.println("MyDHT11Handler的handleTextMessage方法执行了");
        //接收温湿度传递的json数据
        String messagePayload = message.getPayload();
        //收到的都是温湿度的数据,我们需要保存到数据库中
        //时刻将数据写入到数据库会导致数据的并发比较高,其实我们允许丢失一部分数据,先保存到集合当中
        SysHumiture sysHumiture = objectMapper.readValue(messagePayload, SysHumiture.class);
        //设置设备的id
        String deviceId = (String) session.getAttributes().get("name");
        sysHumiture.setDeviceId(deviceId);
        //设置上传数据的时间
        sysHumiture.setUploadTime(new Date());
        //在这里我们就把数据保存到内存中,每隔一段时间批量写入到数据库
        // sysHumitureService.addsysHumiture(sysHumiture);
        //设备id作为键，数据作为值
        humitureHashMultimap.put(deviceId, sysHumiture);
    }


    /**
     * 检查设备心跳
     *
     * @param event
     */

    @Async
    @EventListener
    public void onEvent(SysHumitureCheckEvent event) {
//        humitureHashMultimap.forEach((deviceId, data) -> {
//            System.err.println(deviceId + "------>" + data);
//        });
        //批量插入到数据库
        //取出集合中保存的数据，校验数据是否为空
        Collection<SysHumiture> values = humitureHashMultimap.values();
        if (values == null || values.size() == 0) {
            return;
        }
        //用户新的集合接收数据,防止下面清空的时候导致数据消失
        ArrayList<SysHumiture> sysHumitures = new ArrayList<>(values);
        //清空数据
        humitureHashMultimap.clear();
        //计算平均值,触发任务
        double avg = sysHumitures.stream().mapToDouble(SysHumiture::getTemperature).average().getAsDouble();
        //比如我们约定,如果温度超过30度就给设备发送开的命令, 如果低于25度就发送关的命令
        if (avg >= 30) {
            // System.err.println("打开空调");
            //发送打开空调的事件
            getContext().publishEvent(new DevicePowerCommandEvent("1234567890", "0"));
        } else if (avg <= 25) {
            // System.err.println("关闭空调");
            getContext().publishEvent(new DevicePowerCommandEvent("1234567890", "1"));
        }
        //批量添加
        sysHumitureService.multiAdd(sysHumitures);

    }

    @Override
    public boolean isNeedUpdateOnline() {
        return true;
    }

    @Override
    protected Map<String, Long> getHeartbeatTime() {
        return heartbeatTime;
    }

    @Override
    protected Map<String, WebSocketSession> getAllClient() {
        return allClient;
    }
}
